package org.example.controller;

import com.alibaba.fastjson2.JSONObject;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import org.example.domain.Message;
import org.example.util.WackyUsernameGenerator;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 聊天室
 */
@Component
@ServerEndpoint("/ws/chat")
public class ChatController {

    private static final ConcurrentHashMap<Session,String> sessionMap = new ConcurrentHashMap<>();
    private static final CopyOnWriteArrayList<Message> messages = new CopyOnWriteArrayList<>();
    private Session session;

    // 收到消息
    @OnMessage
    public void onMessage(String message) throws IOException {
        Message msg = new Message();
        msg.setId(UUID.randomUUID().toString());
        msg.setType("text");
        msg.setData(message);
        msg.setSender(sessionMap.get(session));
        msg.setTime(LocalDateTime.now());
        messages.add(msg);
        for (Session session1 : sessionMap.keySet()) {
            msg.setMy(session1 == session);
            String jsonString = JSONObject.toJSONString(msg);
            session1.getBasicRemote().sendText(jsonString);
        }
    }

    // 连接打开
    @OnOpen
    public void onOpen(Session session, EndpointConfig endpointConfig) throws IOException {
        this.session = session;
        sessionMap.put(session, WackyUsernameGenerator.generate());
        for (Message message : messages) {
            message.setMy(false);
            session.getBasicRemote().sendText(JSONObject.toJSONString(message));
        }
    }

    // 连接关闭
    @OnClose
    public void onClose(CloseReason closeReason) {
        sessionMap.remove(this.session);
    }

    // 连接异常
    @OnError
    public void onError(Throwable throwable) throws IOException {
        sessionMap.remove(this.session);// 异常时也从集合中移除
        this.session.close();
    }

}
